using System;
using ValidationFramework.Configuration.Reflection;

namespace ValidationFramework.Specifications
{
	/// <summary>
	/// Specifies that a <see cref="LengthStringRule"/> should be applied to the program element.
	/// </summary>
	/// <seealso cref="LengthStringRule"/>
	/// <example>
	/// <code source="Examples\ExampleLibraryCSharp\Specifications\LengthSpecifications\LengthStringRuleAttributeExample.cs" lang="cs"/>
	/// <code source="Examples\ExampleLibraryVB\Specifications\LengthSpecifications\LengthStringRuleAttributeExample.vb" lang="vbnet"/>
	/// </example>
#if (!SILVERLIGHT)
	[Serializable]
#endif
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.Field, AllowMultiple = true, Inherited = true)]
	public sealed class HasLengthInRangeAttribute : RuleAttribute
	{

		// --- Fields
		private int _minimum;

		// --- Constructor

		/// <param name="maximum">The maximum length allowed.</param>
		public HasLengthInRangeAttribute(int maximum)
		{
			Maximum = maximum;
			Minimum = 0;
			TrimWhiteSpace = false;
		}


		// --- Properties

		/// <summary>
		/// Gets the maximum length.
		/// </summary>
		/// <seealso cref="LengthRule.Maximum"/>
		public int Maximum
		{
			get;
			private set;
		}

		/// <summary>
		/// Gets the minimum length.
		/// </summary>
		/// <exception cref="ArgumentException">Value is less than 0.</exception>
		/// <seealso cref="LengthRule.Minimum"/>
		public int Minimum
		{
			get
			{
				return _minimum;
			}
			set
			{
				if (value < 0)
				{
					throw new ArgumentException("Minimum too low.", "value");
				}
				_minimum = value;
			}
		}

		/// <summary>
		/// Gets or sets a <see cref="bool"/> to indicate if whitespace should be trimmed from the value being validated.
		/// </summary>
		/// <seealso cref="LengthStringRule.TrimWhiteSpace"/>
		public bool TrimWhiteSpace
		{
			get;
			set;
		}


		// --- Methods

		/// <inheritdoc/>
		public override ISpecification CreateSpecification(ICachedReflectionInfo descriptor)
		{
			return new HasLengthInRangeSpec(Minimum, Maximum)
			{
				TrimWhiteSpace = TrimWhiteSpace
			};
		}


	}
}